package springboot.study.project.util.db;

import springboot.study.project.util.common.StringUtil;
import springboot.study.project.util.common.Util;
import springboot.study.project.util.file.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 数据转换工具类
 *
 * @author baoxia
 */
public class FormatDataUtil {

    private static Map<String, Map<String, String>> dbTableInfo = new HashMap<String, Map<String, String>>();

    // 日志
    private static Logger logger = LoggerFactory.getLogger(FormatDataUtil.class);

    /**
     * 对待传入的数据进行根据数据库表字段类型进行转换
     *
     * @param tableName
     * @param data
     * @return
     */
    public static List<Map<String, Object>> formatData(String tableName, List<Map<String, Object>> data) {

        // 获取该表所有的字段名称
        List<String> fieldNameList = DBUtil.getColumnNames(tableName);

        boolean isSave = true; // 保存标志
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> dataMap : data) {
            Map<String, Object> formatDataMap = new HashMap<String, Object>(DBUtil.getAllTableFieldMap().get(tableName.toUpperCase())); // 应该只用初始化一次，放到静态map里：DataAccessConstant.TANLE_FIELD_MAP.get(tableName.toUpperCase()));
            for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
                String fieldName = entry.getKey().toUpperCase();
                Object value = null;

                // 先判断数据库是否有该字段
                if (!StringUtil.isBlank(fieldName) && fieldNameList.contains(fieldName.trim())) {
                    value = getSaveValue(tableName, fieldName, entry.getValue());
                    formatDataMap.put(fieldName, value);
                } else {
                    if (isSave) {
                        try {
                            isSave = false;
                            logger.warn("warn--->" + tableName + "表中没有接入数据的 " + fieldName + " 字段，从数据中进行删除...");
                            FileUtil.writeStringToFile(tableName, fieldName, "./output/not_exist_field.txt");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            if (formatDataMap.size() > 0) {
                resultList.add(formatDataMap);
            }
        }
        return resultList;
    }

    /**
     * 根据表中指定字段类型转换数据类型
     */
    private static Object getSaveValue(String tableName, String colName, Object value) {
        // 获取该表中字段信息
        Map<String, String> tableInfoMap = dbTableInfo.get(tableName);
        if (tableInfoMap == null) {
            tableInfoMap = DBUtil.getColumnNameAndType(tableName);
            dbTableInfo.put(tableName, tableInfoMap);
        }

        String colTypeName = tableInfoMap.get(colName);
        if (colTypeName == null) {
            logger.error("数据库中表" + tableName + "不存在以下字段：" + colName + "，保存失败！");
            throw new RuntimeException("数据库中表" + tableName + "不存在以下字段：" + colName + "，保存失败！");
        }
        Object result = dealSaveValue(value, colTypeName);
//        if ("DIA_BS_EX_ZPS00T_LTLMXB".equals(tableName.toUpperCase()) && "POSID".equals(colName.toUpperCase())) {
//            if (result.toString().length() > 70) {
//                result = result.toString().substring(0, 70);
//            }
//        }
        return result;
    }

    /**
     * 根据保存字段在表中的类型，对保存值进行类型转换和其他处理
     */
    private static Object dealSaveValue(Object value, String colTypeName) {
        Object newValue = null;
        if (value == null) {
            return value;
        } else {
            if ("BIGINT".equals(colTypeName)) {
                if (Util.isNumberByE(value.toString())) {
                    newValue = Long.valueOf(value.toString());
                } else {
                    newValue = Long.valueOf(0);
                }
            } else if ("TINYINT".equals(colTypeName) || "INT".equals(colTypeName) || "INTEGER".equals(colTypeName)) {
                if (Util.isNumberByE(value.toString())) {
                    newValue = Integer.valueOf(value.toString());
                } else {
                    newValue = Integer.valueOf(0);
                }
            } else if ("FLOAT".equals(colTypeName)) {
                if (Util.isNumberByE(value.toString())) {
                    newValue = Float.valueOf(value.toString());
                } else {
                    newValue = Float.valueOf(0);
                }
            } else if ("DOUBLE".equals(colTypeName)) {
                if (Util.isNumberByE(value.toString())) {
                    newValue = Double.valueOf(value.toString());
                } else {
                    newValue = Double.valueOf(0);
                }
            } else if ("DECIMAL".equals(colTypeName)) {
                if (Util.isNumberByE(value.toString()) || true) {
                    newValue = new BigDecimal(value.toString());
                } else {
                    newValue = new BigDecimal(0);
                }
            } else if ("CHAR".equals(colTypeName)) {
                newValue = value.toString();
            } else if ("VARCHAR".equals(colTypeName)) {
                newValue = value.toString();
            } else if ("TEXT".equals(colTypeName)) {
                newValue = value.toString();
            } else if ("DATE".equals(colTypeName) || "DATETIME".equals(colTypeName)) {
                if (StringUtil.isBlank(value)) {
                    newValue = null;
                    // newValue = new Timestamp(getDateFromStr("2028-12-31").getTime());
                } else {
                    Date date = getDateFromStr(value.toString());
                    if (isRightDateRange(date)) {
                        newValue = new Timestamp(getDateFromStr(value.toString()).getTime());
                    } else {
                        newValue = null;
                        // newValue = new Timestamp(getDateFromStr("2028-12-31").getTime());
                    }
                }
            } else if ("TIMESTAMP".equals(colTypeName)) {
                if (StringUtil.isBlank(value)) {
                    newValue = null;
                    // newValue = new Timestamp(getDateFromStr("2028-12-31").getTime());
                } else {
                    Date date = getDateFromStr(value.toString());
                    if (isRightTimestampRange(date)) {
                        newValue = new Timestamp(date.getTime());
                    } else {
                        newValue = null;
                        // newValue = new Timestamp(getDateFromStr("2028-12-31").getTime());
                    }
                }
            } else if ("TIME".equals(colTypeName)) {
                if (value == null) {
                    newValue = null;
                } else if (StringUtil.isNumber(value.toString()) && value.toString().length() <= 6) {
                    newValue = value.toString();
                } else {
                    newValue = "";
                }
            } else {
                logger.warn("数据库保存时出现非常用类型：" + colTypeName + "，value值为：" + value);
                // newValue = null;
                newValue = value;
            }
        }
        return newValue;
    }

    // 日期转换
    private static Date getDateFromStr(String sourceStr) {
        String dateStr = sourceStr;
        // String，从to_date()方法的字符串中获取时间数据
        if (dateStr.contains("(")) {
            dateStr = dateStr.substring(dateStr.indexOf("("));
            String[] splitStr = dateStr.split("'");
            if (dateStr.contains("'")) {
                if (splitStr.length >= 2) {
                    dateStr = splitStr[1];
                } else if (StringUtil.isBlank(splitStr[0])) {
                    return new Date();
                } else if (!StringUtil.isBlank(splitStr[0])) {
                    dateStr = splitStr[0];
                }
            } else {
                dateStr = dateStr.replaceAll(")", "");
            }
        }
        String[] fmtArr = {"yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "yyyy-MM", "yyyyMMdd", "yyyyMM"};
        Date date = null;
        for (String fmtStr : fmtArr) {
            DateFormat fmt = new SimpleDateFormat(fmtStr);
            try {
                date = fmt.parse(dateStr);
                break;
            } catch (ParseException e) {
                continue;
            }
        }
        if (date == null) {
            try {
                // Date dateValue = new Date();
                Date dateValue = new SimpleDateFormat("yyyy-MM-dd").parse("2029-12-31");
                logger.warn("执行数据库保存时，日期类型数据转换异常，原始数据为：" + sourceStr + "，将保存以下值：" + dateValue);
                return dateValue;
            } catch (ParseException e) {
                e.printStackTrace();
                return new Date();
            }
        } else {
            return date;
        }
    }

    // 判断时间戳类型是否再指定范围
    public static boolean isRightDateRange(Date date) {
        String beginTime = new String("1970-01-01 08:00:01");
        String endTime = new String("2200-01-19 11:14:07");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date begin = null;
        Date end = null;
        try {
            begin = df.parse(beginTime);
            end = df.parse(endTime);
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }

        if (date.compareTo(begin) > 0 && date.compareTo(end) < 0) {
            return true;
        } else {
            return false;
        }
    }

    // 判断时间戳类型是否再指定范围
    public static boolean isRightTimestampRange(Date date) {
        String beginTime = new String("1970-01-01 08:00:01");
        String endTime = new String("2038-01-19 11:14:07");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date begin = null;
        Date end = null;
        try {
            begin = df.parse(beginTime);
            end = df.parse(endTime);
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }

        if (date.compareTo(begin) > 0 && date.compareTo(end) < 0) {
            return true;
        } else {
            return false;
        }
    }


    public static void main(String[] args) throws ParseException {
        String str1 = "011333";
        String str = "20530711";
        String str2 = "223145";
        // System.out.println(new Timestamp(getNewDate(str).getTime()));
        Date date = new SimpleDateFormat("yyyyMMdd").parse("20380102");
        System.out.println(isRightTimestampRange(date));

    }
}
